package com.example.springtest.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.example.springtest.DataTree;
import com.google.gson.*;
import org.springframework.beans.BeanUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @Author: HuoYongZhuang
 * @create 2022/11/25
 */

/**
 * 判断两个json是否相同
 *
 */

public class JsonUtils {

   private static final Gson gson = new Gson();

    //判断JsonElement是否想等
    private static boolean same(JsonElement a, JsonElement b,Boolean isRelativelyValue){
        if (a.isJsonObject() && b.isJsonObject()){
            return same((JsonObject) a,(JsonObject) b,isRelativelyValue);
        }else if(a.isJsonArray() && b.isJsonArray()){
            return same((JsonArray) a,(JsonArray) b,isRelativelyValue);
        }else if(a.isJsonPrimitive() && b.isJsonPrimitive()){
            return same((JsonPrimitive) a,(JsonPrimitive) b,isRelativelyValue);
        }else if(a.isJsonNull() && b.isJsonNull()){
            return same((JsonNull) a,(JsonNull) b);
        }else {
            return Boolean.FALSE;
        }
    }

    /**
     * 递归判断两个JsonObject是否相同
     * @param a
     * @param b
     * @return
     */
    public static boolean same(JsonObject a, JsonObject b,Boolean isRelativelyValue){
        Set<String> aSet = a.keySet();
        Set<String> bSet = b.keySet();
        if (!aSet.equals(bSet)){
            return false;
        }
        for (String akey:aSet){

            if(!same(a.get(akey),b.get(akey),isRelativelyValue)){
                return  false;
            }
        }
       return true;

    }

    /**
     * 判断两个jsonString 是否相同
     */
    public static boolean same(String aa, String bb,Boolean isRelativelyValue){
        JsonParser jsonParser = new JsonParser();
        JsonObject jsonObject1 = (JsonObject) jsonParser.parse(aa);
        JsonParser parser1 = new JsonParser();
        JsonObject jsonObject2 = (JsonObject) parser1.parse(bb);
        Set<String> aSet = jsonObject1.keySet();
        Set<String> bSet = jsonObject2.keySet();
        if (!aSet.equals(bSet)){
            return false;
        }
        for (String akey:aSet){
            if(!same(jsonObject1.get(akey),jsonObject2.get(akey),isRelativelyValue)){
                return  false;
            }
        }
        return true;
    }

    //判断两个jsonArray 是否想等
    private static boolean same(JsonArray a, JsonArray b,Boolean isRelativelyValue){
        if(a.size() !=b.size()){
            return false;
        }
        List<JsonElement> aList = toSortedList(a);
        List<JsonElement> bList = toSortedList(b);
        for (int i = 0; i <aList.size() ; i++) {
                if(!same(aList.get(i),bList.get(i),isRelativelyValue)){
                    return false;
                }
        }
        return  true;
    }


    private static List<JsonElement> toSortedList(JsonArray jsonElements){
        List<JsonElement> aList = new ArrayList<>();
        jsonElements.forEach(aList::add);
        aList.sort(Comparator.comparing(gson::toJson));
        return aList;
    }

    private static boolean same(JsonPrimitive a,JsonPrimitive b, Boolean isRelativelyValue){
        Boolean is = true;
        if (isRelativelyValue){
           is = a.equals(b);
        }
        return is;

    }

    private static boolean same(JsonNull a, JsonNull b){
        return a.equals(b);
    }


    /**
     *  jsonObject转 树结构
     * @param jsonObject
     * @return
     */
    public static JSONArray JsonConversionObjTree(JsonObject jsonObject){
        DataTree dataTree = new DataTree();
        List<DataTree> dataTrees = JsonUtils.convertJson2KvObj(jsonObject, dataTree);
        //将list转换为jsonArray
        JSONArray array= JSONArray.parseArray(JSON.toJSONString(dataTrees));
        return array;
    }


    private static List<DataTree> convertJson2KvObj(JsonObject json,DataTree dataTree){
        List<DataTree> objList = new ArrayList<>();

        for(Map.Entry<String, JsonElement> entry : json.entrySet()){
            DataTree dataTree1 = new DataTree();
            //JsonObject
            if(entry.getValue() instanceof JsonObject){
                dataTree1.setType("JsonObject");
                if(dataTree.getField()!=null){
                    dataTree1.setField(dataTree.getField()+ "." + entry.getKey());
                    dataTree1.setPField(dataTree.getField());
                }else {
                    dataTree1.setField(entry.getKey());
                }
                //递归
                dataTree1.setChildren(convertJson2KvObj((JsonObject) entry.getValue(),dataTree1));
                //数组
            }else if(entry.getValue() instanceof JsonArray){
                List<JsonElement> aList = toSortedList((JsonArray)entry.getValue());
                List<DataTree> list = new ArrayList<>();
                for (JsonElement jsonElement: aList){
                    list = convertJson2KvObj((JsonObject) jsonElement,dataTree1);
                }
                if(dataTree.getField()!=null){
                    dataTree1.setField(dataTree.getField()+ "." + entry.getKey());
                    dataTree1.setPField(dataTree.getField());
                }else {
                    dataTree1.setField(entry.getKey());
                }
                dataTree1.setType("JsonArray");
                List<DataTree> collect = list.stream().map(dataTree2 -> {
                    DataTree dataTree3 = new DataTree();
                    BeanUtils.copyProperties(dataTree2, dataTree3);
                    if (dataTree1.getField() != null) {
                        dataTree3.setField(dataTree1.getField() + "." + dataTree2.getField());
                        dataTree3.setPField(dataTree1.getField());
                    }
                    return dataTree3;
                }).collect(Collectors.toList());
                dataTree1.setChildren(collect);
            }else{
                List<DataTree> objList1 = new ArrayList<>();
                if(dataTree.getField()!=null){
                    dataTree1.setField(dataTree.getField()+ "." + entry.getKey());
                    dataTree1.setPField(dataTree.getField());
                }else {
                    dataTree1.setField(entry.getKey() == null ? null : entry.getKey());
                }

                JsonElement jsonElement = entry.getValue();
                if(jsonElement.getAsJsonPrimitive().isString()){
                    dataTree1.setType("String");
                }else if(jsonElement.getAsJsonPrimitive().isNumber()){
                    dataTree1.setType("Integer");
                }
                dataTree1.setChildren(objList1);
            }
            objList.add(dataTree1);
        }
        return objList;
    }


}
